package cn.ac.jaas.isc.vegetable.common.xss.core;

import cn.ac.jaas.isc.vegetable.common.xss.config.VegetableXssProperties;
import cn.ac.jaas.isc.vegetable.common.xss.utils.XssUtil;
import cn.hutool.core.util.CharsetUtil;
import lombok.RequiredArgsConstructor;
import org.jsoup.Jsoup;
import org.jsoup.internal.StringUtil;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Entities;
import org.jsoup.safety.Cleaner;
import org.springframework.web.util.HtmlUtils;

/**
 * @author 张高昌
 * @date 2022/4/23 20:31
 * @description: 功能描述
 */
@RequiredArgsConstructor
public class DefaultXssCleaner implements XssCleaner {

    private final VegetableXssProperties properties;

    @Override
    public String clean(String bodyHtml) {
        // 1. 为空直接返回
        if (StringUtil.isBlank(bodyHtml)) {
            return bodyHtml;
        }
        VegetableXssProperties.Mode mode = properties.getMode();
        if (VegetableXssProperties.Mode.escape == mode) {
            // html 转义
            return HtmlUtils.htmlEscape(bodyHtml, CharsetUtil.UTF_8);
        } else {
            // jsoup html 清理
            Document.OutputSettings outputSettings = new Document.OutputSettings()
                    // 2. 转义，没找到关闭的方法，目前这个规则最少
                    .escapeMode(Entities.EscapeMode.xhtml)
                    // 3. 保留换行
                    .prettyPrint(properties.isPrettyPrint());
            Document dirty = Jsoup.parseBodyFragment(bodyHtml, "");
            Cleaner cleaner = new Cleaner(XssUtil.WHITE_LIST);
            Document clean = cleaner.clean(dirty);
            clean.outputSettings(outputSettings);
            // 4. 清理后的 html
            String escapedHtml = clean.body().html();
            if (properties.isEnableEscape()) {
                return escapedHtml;
            }
            // 5. 反转义
            return Entities.unescape(escapedHtml);
        }
    }
}
